import platform = require('../common/baseCommon');
import appClient = require('./appClient');
import platformControls = require('./controls');
import echartControl = require('./echartControls')

/**
 * 模块名称
 */
const moduleName: string = "platform.client";
type alignType = "tool-align-left" | "tool-align-right";

/**
 * 工具按钮控件
 */
@platform.addon("工具按钮控件", "智能报表模块工具条按钮", moduleName)
@appClient.template(`<button class="btn btn-default" style="padding: 3px 5px;margin-top: 3px;" type="button"></button>`)
export class toolControl extends appClient.baseControl {
    /** glyphicon 图标 */
    icon?: string;
    /** 显示图标 */
    showIcon?: boolean;
    /** 显示边 */
    showBorder?: boolean;
    /** 当前点击的控件 */
    currentControl?: appClient.baseControl;
    /** 点击事件 */
    onClick?() {

    }
    /**
     * 绑定后事件处理
     */
    doAfterBind?() {

    }
    onAfterBind?() {
        if (this.icon && this.showIcon) {
            let em = document.createElement("em");
            $(em).addClass(this.icon);
            $(em).appendTo(this.element);
        }
        if (!this.showBorder) {
            $(this.element).addClass("btn-link");
        }
        $(this.element).click(() => {
            this.onClick();
        });
        if (this.doAfterBind) {
            this.doAfterBind();
        }
    }
}

@platform.addon("放大", "放大按钮", moduleName)
export class zoominToolControl extends toolControl {
    /** 按钮默认图标 */
    private defaultIcon?: string = "glyphicon glyphicon-zoom-in";
    private tempDialogHtml?: string = `<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-sm" style="width:70%;left:15%;" role="document"><div class="modal-content"><div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h4 class="modal-title" name="title"></h4>
    </div><div class="modal-body"><div class="container-fluid" name="body"></div></div></div></div></div>`;
    constructor() {
        super();
        this.icon = this.defaultIcon;
        this.showIcon = true;
        this.showBorder = false;
    }
    onClick?() {
        let module = <baseReportModule>this.currentControl;
        let dialog = $(this.tempDialogHtml);
        let titleContainer = $(dialog).find('h4[name="title"]');
        let bodyContainer = $(dialog).find('div[name="body"]');
        $(titleContainer).text(module.caption);
        if (platform.reflect.isTypeOf(module, baseEchartDataDisplayer)) {
            let dom = document.createElement("div");
            $(dom).addClass("col-md-12 column text-center");
            let echartModule = <baseEchartDataDisplayer>module;
            let height = echartModule.element.clientHeight + 'px';
            let options = echartModule.options;
            $(dom).height(height);
            $(dom).width("200px");
            $(dom).appendTo(bodyContainer);
            let chart = echarts.init(dom);
            chart.setOption(options);
        } else {
            let body = module.element.innerHTML.slice(0);
            $(body).appendTo(bodyContainer);
        }
        dialog.modal();
    }
}

@platform.addon("查询按钮", "查询按钮", moduleName)
@appClient.template(`<button class=" btn btn-primary" type="button">查询</button>`)
export class queryToolControl extends toolControl {
    /**
     * 点击事件处理
     */
    clickEvent?: platform.event<() => void> = new platform.event<() => void>();

    constructor() {
        super();
        this.showBorder = true;
    }

    onClick?() {
        if (this.clickEvent)
            this.clickEvent.fire();
    }
}


@platform.addon("显示按钮", "显示按钮", moduleName)
export class showToolControl extends toolControl {
    /** 显示对象ID */
    showItemID?: string;
    /** 适应对象ID */
    adaptionID?: string;
    private defaultIcon?: string = "report-icon report-icon-show";
    constructor() {
        super();
        this.icon = this.defaultIcon;
        this.showIcon = true;
        this.showBorder = true;
    }
    onClick?() {
        $(this.showItemID).collapse('show');
        $(this.adaptionID).removeClass('showed');
    }
}

@platform.addon("隐藏按钮", "隐藏按钮", moduleName)
export class hideToolControl extends toolControl {
    /** 显示对象ID */
    showItemID?: string;
    /** 适应对象ID */
    adaptionID?: string;
    private defaultIcon?: string = "report-icon report-icon-hide";
    constructor() {
        super();
        this.icon = this.defaultIcon;
        this.showIcon = true;
        this.showBorder = true;
    }
    onClick?() {
        $(this.showItemID).collapse('hide');
        $(this.adaptionID).addClass('showed');
    }
}

/**
 * 名称:自动查询按钮
 * @description 用于智能报表数据源自动查询的开关
 * @author 胡燕龙(huyl)
 */
@platform.addon('自动查询按钮', '用于智能报表数据源自动查询的开关', moduleName)
export class autoQueryToolControl extends toolControl {
    open?: boolean = true;
    /** 点击事件 */
    clickEvent?: platform.event<() => boolean> = new platform.event<() => boolean>();
    /** 图标:自动查询开启 */
    private defaultOpenIcon = "report-icon report-icon-refresh-open";
    /** 图标:自动查询关闭 */
    private defaultCloseIcon = "report-icon report-icon-refresh-close";
    /** 自动查询按钮 */
    constructor() {
        super();
    }
    onClick?() {
        if (this.clickEvent.have) {
            this.clickEvent.fire();
        }
    }
}

/**
 * 工具箱
 */
@platform.addon("工具箱", "工具箱按钮组", moduleName)
@appClient.template(`<div class="btn-group"></div>`)
export class toolBoxControl extends appClient.baseControl {
    /** 工具按钮 */
    tools?: toolControl[];
    /** 工具箱按钮位置 */
    align?: alignType;
    onAfterBind?() {
        for (let tool of this.tools) {
            tool.appendTo(this.element);
        }
    }
}

/**
 * 基础报表模块
 */
@platform.addon("基础报表模块", "可以插入到智能报表的模块,模块主体放入$report容器中,并实现onAfterBindEvent事件", moduleName)
export class baseReportModule extends appClient.baseControl {
    /** 模块名称 */
    name?: string;
    /** 模块标题 */
    caption?: string;
    /** 自定义工具箱 */
    customToolBox?: toolBoxControl;
    /** 
     * 模块组名
     * @remark 存在组名时报表模块放入标签页容器中 
     */
    groupName?: string;
    /** 视图列表 */
    dataViews?: platform.dataView[string];
    /** 列配置项 */
    columns?: gridColumn[] | booleanColumn[] | dateColumn[] | numberColumn[] | templateColumn[];
}

@platform.addon("报表控件模块容器", "报表控件模块容器,用于报表模块的外框部分及自定义按钮", moduleName)
@appClient.template(`<div class="container-fluid moduleDiv" style="border: 1px solid;border-radius:5px;height:100%;">
<div class="row-fluid"><div class="col-sm-12 col-md-12 column" name="toolbox">
<h5 class="moduleCaption" name="caption"></h5></div>
</div><div class="row-fluid moduleReport" name="report" style="border-top: 1px solid;padding:5px 5px;height:91%;overflow:auto;"></div></div>`, "platform/client/report.css")
export class moduleContainerControl extends appClient.baseControl {

    /** 标题容器 */
    $caption?: JQuery = undefined;
    /** 工具箱容器 */
    $toolbox?: JQuery = undefined;
    /** 报表模块容器 */
    $report?: JQuery = undefined;
    $headerRow?: JQuery = undefined;
    /** 报表模块 */
    module?: appClient.baseControl;
    /** 默认工具箱位置 */
    private defaultAlign?: alignType = "tool-align-right";
    onAfterBind?() {
        let module = this.module;
        if (module) {
            if (module.customToolBox) {
                let tools = module.customToolBox.tools;
                let align = module.customToolBox.align ?
                    module.customToolBox.align : this.defaultAlign;

                for (let tool of tools) {
                    tool.currentControl = module;
                }
                module.customToolBox.appendTo($(this.$toolbox));
                $(module.customToolBox.element).addClass(align);
            }
            if (module.caption) {
                this.$caption.text(module.caption);
            } else {
                this.$caption.remove();
            }
            module.appendTo($(this.$report));
        }
    }
}

/**
 * 标签页容器
 */
@platform.addon('标签页容器', '标签页容器', moduleName)
@appClient.template(`<div class="container-fluid moduleTab" style="border: 1px solid;border-radius:5px;width:100%;height:100%">
    <div name="multilabel" style="width:100%;" class="tabdiv">
        <button type="button" class="btn btn-Previous btn-tab"><em class="glyphicon glyphicon-chevron-left"></em></button>
        <ul name="tabNav" class="nav nav-tabs tabul"></ul>
        <button type="button" class="btn btn-next btn-tab"><em class="glyphicon glyphicon-chevron-right"></em></button>
    </div>
    <div name="tabContent" class="tab-content" style="width:100%;height:90%;overflow:auto;"></div>
</div>`)
export class tabContainerControl extends appClient.baseControl {
    /** tab导航容器 */
    $tabNav?: JQuery = undefined;
    /** tab内容页容器 */
    $tabContent?: JQuery = undefined;
    /** tab外层容器*/
    $multilabel?: JQuery = undefined;
    /** 报表模块列表 */
    modules?: appClient.baseControl[];
    /** tab导航id格式 */
    private tabNavFormat?: string = "tabNav_{0}";
    /** tab内容页id格式 */
    private tabContentFormat?: string = "tabContent_{0}";
    /** tab导航html格式 */
    private tabNavHtml?: string = `<li class="tabli" style="display:inline-block; float:none"><a href="#{0}" data-toggle="tab">{1}</a></li>`;
    /** tab内容页html格式 */
    private tabContentHtml?: string = `<div class="tab-pane fade" id="{0}"></div>`;
    onAfterBind?() {
        let that = this;
        let tabNavID = platform.format(this.tabNavFormat, this.name);
        let tabContentID = platform.format(this.tabContentFormat, this.name);
        $(this.$tabNav).attr("id", tabNavID);
        $(this.$tabContent).attr("id", tabContentID);
        if (this.modules.length > 0) {
            for (let item of this.modules) {
                let module = <baseReportModule>item;
                let nav = platform.format(this.tabNavHtml, module.name, module.caption);
                let content = platform.format(this.tabContentHtml, module.name);
                $(nav).appendTo(this.$tabNav);
                $(content).appendTo(this.$tabContent);
                $(`#${module.name}`).addClass("active");
                module.appendTo($(`#${module.name}`));
            }
            // 显示第一个报表模块
            $(`#${tabNavID} li:eq(0) a`).tab('show');
        }
        $(".btn-next").click(function () {
            let scr = $(that.$tabNav).scrollLeft();
            $(this).prev().scrollLeft(scr + 50);
        });
        $(".btn-Previous").click(function () {
            let scr = $(that.$tabNav).scrollLeft();
            $(this).next().scrollLeft(scr - 50);
        });
        //计算ul 下li宽度总和判断是否要产生滚动条与左右点击按钮
        var sumWidth = 0;
        $(this.$tabNav).find("li").each(function () {
            sumWidth += $(this).width();
        });
        if (sumWidth > $(this.$tabNav).width()) {
            $(this.element).find("button").css("display", "block");
            //为tab外层添加较小的高度，ul添加较高的高度使其覆盖滚动条
            $(that.$multilabel).css("height", "42px");
            $(that.$tabNav).css("height", "58px");
        }
        $(this.element).resize(function () {
            if (sumWidth > $(that.$tabNav).width()) {
                $(that.element).find("button").css("display", "block");
                $(that.$multilabel).css("height", "42px");
                $(that.$tabNav).css("height", "58px");
            } else {
                $(that.element).find("button").css("display", "none");
                $(that.$multilabel).css("height", "42px");
                $(that.$tabNav).css("height", "42px");
            }
        });
    }
}

/**
 * 数据查询器
 */
export interface dataQueryer {
    /**
     * 级联数据源名称列表
     */
    dataSourceNames?: string[];
    /**
     * 查询
     */
    query?: () => void;
    /**
     * 事件:执行查询
     */
    doQuery?: (dataSourceName: string, paramValues: any[string], startIndex: number, maxCount: number) => void;
    /**
     * 自动查询时间间隔（单位：毫秒），如果大于零，表示自动执行；如果小于等于0，表示手动执行
     */
    autoQueryInterval?: number;
    /** 
     * 事件分页查询
     */
    doPageQuery?: (dataSourceName: string, startIndex: number, maxCount: number) => Promise<any>;
}

/**
 * 数据显示器
 */
export interface dataDisplayer {
    /**
     * 清除数据
     */
    clearData?(): void;
    /**
     * 准备数据格式
     */
    prepareDataSchema?(table: any): void;
    /**
     * 添加数据
     */
    setData?(data: any): void;
}

/**
 * 判断模块是否为查询器
 * @param module 报表模块
 */
function isQueryer(module: baseReportModule): module is dataQueryer {
    return (<dataQueryer>module).query !== undefined;
}

/**
 * 判断模块是否为显示器
 * @param module 报表模块
 */
function isDisplayer(module: baseReportModule): module is dataDisplayer {
    return (<dataDisplayer>module).setData !== undefined;
}

/**
 * 智能报表
 */
@platform.addon("智能报表", "可以灵活配置的智能报表", moduleName)
@appClient.template('<div></div>')
export class smartReport extends appClient.baseView implements appClient.supportParameters {
    /** 报表模块 */
    modules?: baseReportModule[string];
    /** 布局面板 */
    layoutPanel?: platformControls.layoutPanel;
    /** 数据源列表 */
    dataSources?: platform.baseDataSource[string];
    /** 是否开启自动查询 */
    autoQuery?: boolean;
    /** 
     * 请求参数键值 
     */
    requestParameterKeys?: string[];
    /** 自动查询标志 */
    private autoQueryInterval = [];
    /** 外部默认请求参数 */
    private defaultParams = {};
    /** 
     * 报表模块初始化
     * @remark 初始化报表模块外框控件(标题,工具箱)
     */
    initialize?() {
        let containers: any[string] = {};
        for (let key in this.modules) {
            if (key == platform.proto) continue;
            let module = this.modules[key];
            if (module.groupName) {
                let moduleContainer = containers[module.groupName]
                    ? containers[module.groupName]
                    : new tabContainerControl();
                if (!(moduleContainer.modules)) {
                    moduleContainer.modules = [];
                }
                moduleContainer.name = module.groupName;
                moduleContainer.modules.push(module);
                containers[module.groupName] = moduleContainer;
            } else {
                let moduleContainer = new moduleContainerControl();
                moduleContainer.module = module;
                containers[module.name] = moduleContainer;
            }
        }
        for (let name in containers) {
            if (name == platform.proto) continue;
            let container = containers[name];
            this.layoutPanel.addChild(name, container);
        }
        this.layoutPanel.appendTo(this.element);
        let captionContainer = $(this.layoutPanel.element).find(`h3[name="reportCaption"]`);
        if (this.caption) {
            captionContainer.text(this.caption);
        }

        //设置自动查询开关
        let refreshSwitch = $(this.layoutPanel.element).find(`button[name="refreshSwitch"]`);
        if (refreshSwitch) {
            let that = this;
            let refreshImg = refreshSwitch.children('img');
            let openImgPath = "project/test/config/client/smartReportApp/layout/images/refresh-open.png";
            let closeImgPath = "project/test/config/client/smartReportApp/layout/images/refresh-close.png";
            let openTitle = "自动查询：开";
            let closeTitle = "自动查询：关";
            if (this.autoQuery) {
                refreshImg.attr('src', openImgPath);
                refreshImg.attr('title', openTitle);
            } else {
                refreshImg.attr('src', closeImgPath);
                refreshImg.attr('title', closeTitle);
            }
            refreshSwitch.click(() => {
                if (that.autoQuery) {
                    that.onCloseAutoQuery();
                    refreshImg.attr('src', closeImgPath);
                    refreshImg.attr('title', closeTitle);
                } else {
                    that.onOpenAutoQuery();
                    refreshImg.attr('src', openImgPath);
                    refreshImg.attr('title', openTitle);
                }
            });
        }

    }
    /** 数据视图初始化 */
    initializeViews?(module: baseReportModule, dataViews: platform.dataView[string]) {
        for (let viewName in dataViews) {
            if (viewName == platform.proto) continue;
            let view = <platform.dataView>dataViews[viewName];
            for (let sourceName in this.dataSources) {
                if (sourceName == platform.proto) continue;
                let source = <platform.baseDataSource>this.dataSources[sourceName];
                source.onQueryEvent.register(table => {
                    view.onQuery(table);
                });
                source.onInitTableSchemaEvent.register(table => {
                    view.onInitTableSchema(table);
                })
            }
            // 显isDisplayer示模块,触发数据变化显示事件
            if (isDisplayer(module)) {
                view.onQueryEvent.register(table => {
                    //如果联动的分页模块，就需要清空数据。
                    module.clearData();
                    appClient.hideLoading();
                    module.setData(table);
                });
                view.onInitTableSchemaEvent.register(table => {
                    appClient.hideLoading();
                    module.prepareDataSchema(table);
                });
            }
        }
        // 查询模块,执行查询动作
        if (isQueryer(module)) {
            module.doQuery = (dataSourceName: string, paramValues: any[string], startIndex: number, maxCount: number) => {
                appClient.showLoading(`数据查询中...`);
                // 通过数据源查询数据,并过滤返回的数据
                // 没有过滤则直接返回查询的结果
                if (!this.dataSources[dataSourceName])
                    return undefined;
                let realParams = {};
                platform.reflect.propertyCopy(realParams, paramValues);
                platform.reflect.propertyCopy(realParams, this.defaultParams);
                let source = platform.getObject<platform.baseDataSource>(this.dataSources[dataSourceName]);
                source.query(realParams, startIndex, maxCount).catch(error => {
                    appClient.hideLoading();
                    platform.log(`数据源:${dataSourceName}执行查询发生异常:${error.message}`);
                    appClient.alerts("查询数据异常", error.message, appClient.alertType.error);
                });
            }
            //分页查询
            module.doPageQuery = (dataSourceName: string, startIndex: number, maxCount: number) => {
                if (!this.dataSources[dataSourceName])
                    return undefined;
                let source = platform.getObject<platform.baseDataSource>(this.dataSources[dataSourceName]);
                return source.pageQuery(startIndex, maxCount);
            }
        }
    }
    /**
     * 事件:绑定后
     * @remark 初始化查询事件,初始化数据变化事件
     * 1. 查询动作->(1)->数据视图->(2)->数据源->(3)->获取器
     * 2. 获取器->(1)变化->数据源->(2)变化->数据视图->(3)筛选(4)变化->图表
     */
    onAfterBind?(): void {
        // 初始化数据源,数据视图
        for (let key in this.modules) {
            if (key == platform.proto) continue;
            let module = this.modules[key];
            let dataViews = module.dataViews;
            this.initializeViews(module, dataViews);
        }
        // 报表容器初始化
        this.initialize();
        // 初始化表结构
        for (let key in this.dataSources) {
            if (key == platform.proto) continue;
            let dataSource = this.dataSources[key];
            appClient.showLoading("数据初始化...");
            dataSource.initTableSchema().catch(error => {
                appClient.hideLoading();
                platform.log(`数据初始化发生异常:${error.message}`);
                appClient.alerts("数据初始化错误", error.message, appClient.alertType.error);
            });
        }
        if (this.autoQuery) {
            this.onOpenAutoQuery();
        }
    }

    /**
     * 事件：打开自动查询
     */
    onOpenAutoQuery?() {
        for (let key in this.dataSources) {
            if (key == platform.proto) continue;
            let dataSource = platform.getObject(this.dataSources[key]);
            if (dataSource.autoQuery) {
                appClient.showLoading(`数据查询中...`);
                dataSource.query(undefined, 0, Number.MAX_SAFE_INTEGER).catch(error => {
                    appClient.alerts("数据加载错误", error.message, appClient.alertType.error);
                });
                if (dataSource.autoQueryInterval > 0) {
                    let interval = setInterval(() => {
                        dataSource.query(undefined, 0, Number.MAX_SAFE_INTEGER).catch(error => {
                            appClient.alerts("数据加载错误", error.message, appClient.alertType.error);
                        });
                    }, dataSource.autoQueryInterval);
                    this.autoQueryInterval.push(interval);
                }
            }
        }
        // for (let key in this.modules) {
        //     if (key == platform.proto) continue;
        //     let module = this.modules[key];
        //     if (isQueryer(module)) {
        //         module.query();
        //         if (module.autoQueryInterval > 0) {
        //             let interval = setInterval(() => {
        //                 module.query();
        //             }, module.autoQueryInterval);
        //             this.autoQueryInterval.push(interval);
        //         }
        //     }
        // }
        this.autoQuery = true;
    }

    /**
     * 事件:关闭自动查询
     */
    onCloseAutoQuery?() {
        for (var index = 0; index < this.autoQueryInterval.length; index++) {
            let interval = this.autoQueryInterval[index];
            clearInterval(interval);
            // 删除当前元素,并重新遍历
            this.autoQueryInterval.splice(index, 1);
            index -= 1;
        }
        this.autoQuery = false;
    }
    /** 获取参数键值列表 */
    getParameterKeys?(): string[] {
        if (this.requestParameterKeys)
            return this.requestParameterKeys;
        return undefined;
    }
    /** 设置参数值 */
    setRequestParameterValue?(paramValues: any[string]) {
        if (!this.defaultParams) this.defaultParams = {};
        platform.reflect.propertyCopy(this.defaultParams, paramValues);
    }
}

@platform.addon('基础智能报表模块', '用于嵌套的智能报表模块,包含智能报表', moduleName)
@appClient.template(`<div></div>`)
export class baseSmartReportModule extends baseReportModule {
}

@platform.addon('智能报表模块', '用于嵌套智能报表的模块', moduleName)
export class smartReportModule extends baseSmartReportModule {
    /** 嵌套的智能报表 */
    report?: smartReport;
    onAfterBind?() {
        // 将报表添加到
        this.report.appendTo(this.element);
    }
}

/**
 * 字段编辑信息
 */
@platform.addon("字段编辑信息", "包含了字段的信息和编辑器信息", moduleName)
export class fieldEditInfo extends platform.dataField {
    /** 编辑器控制器 */
    editControl?: platformControls.baseEditControl;
    /** 编辑器数据源 */
    dataSource?: platform.baseDataSource;
    /** 默认数据 */
    defaultData?: any;
    /** 绑定数据 */
    bindFieldEditControlData?() {
        if (this.defaultData) {
            this.editControl.setData(this.defaultData);
        } else {
            if (this.dataSource) {
                this.dataSource.initQuery()
                    .then((table: platform.dataTable) => {
                        // 表数据不为空且行数据存在
                        if (table && table.rows.length > 0) {
                            let data = [];
                            table.rows.forEach((row, index) => {
                                data.push(row.rowValues);
                            });
                            this.editControl.setData(data);
                        }
                    }).catch(error => {
                        platform.log(`编辑器绑定数据错误:${error.message ? error.message : error}`)
                    });
            }
        }
    }
}

/**
 * 参数控制器
 */
@platform.addon("参数控制器", "用于输入参数的参数控制器", moduleName)
@appClient.template(`<div><div name="fieldContainers"></div>
<div class="input-group"></div></div>`)
export class parameterControl extends baseReportModule implements dataQueryer {
    /**
     * 字段列表
     */
    fields?: fieldEditInfo[];
    /**
     * 自动查询时间间隔
     */
    autoQueryInterval?: number;
    /**
     * 单次查询数量
     */
    queryCount?: number;
    private startIndex?: number = 0;
    /**
     * 数据源名称
     */
    dataSourceNames?: string[];
    /**
     * 字段容器
     */
    $fieldContainers?: JQuery = undefined;
    /**
     * 查询按钮控件
     */
    private queryBtn?: queryToolControl;

    constructor() {
        super();
        //创建查询按钮
        if (!this.customToolBox) {
            this.customToolBox = new toolBoxControl();
            this.customToolBox.tools = [];
        }
        this.queryBtn = new queryToolControl();
        //绑定查询事件
        this.customToolBox.tools.push(this.queryBtn);
    }

    /**
     * 事件:执行查询
     */
    doQuery?: (dataSourceName: string, paramValues: any[string], startIndex: number, maxCount: number) => void;
    /**
     * 获取参数值
     * @return 参数值
     */
    getParamValues?(): any[string] {
        let paramValues = {};
        if (this.fields) {
            for (let field of this.fields) {
                let value = field.editControl.getValue();
                if (value) {
                    paramValues[field.name] = field.editControl.getValue();
                }
            }
        }
        return paramValues;
    }
    /**
     * 查询
     */
    query?(): void {
        if (!this.queryCount)
            this.queryCount = 500;
        // 执行查询
        if (this.dataSourceNames) {
            for (let dataSourceName of this.dataSourceNames) {
                if (this.doQuery)
                    this.doQuery(dataSourceName, this.getParamValues(), this.startIndex, this.queryCount);
            }
        }
    }
    onAfterBind?(): void {
        // 创建编辑器控件
        for (let field of this.fields) {
            let createSign = false;
            // 先添加控件
            field.editControl.appendTo(this.$fieldContainers);
            // 添加空行
            $('<br>').appendTo(this.$fieldContainers);
            //在绑定数据
            field.bindFieldEditControlData();
        }
        //绑定查询事件
        this.queryBtn.clickEvent.register(() => {
            this.query();
        });
    }
}

/**
 * 基础数据显示器
 */
@platform.addon("基础数据显示器", "所有数据显示器的基类", moduleName)
@appClient.template('<div></div>')
export abstract class baseDataDisplayer extends baseReportModule implements dataDisplayer {
    /**
     * 显示数据
     */
    abstract setData?(data: any): void;
    /**
     * 清除数据
     */
    abstract clearData?(): void;
    /**
     * 准备数据格式
     */
    abstract prepareDataSchema?(table: any): void;
}

/**
 * EChart图表数据显示器
 */
@platform.addon('EChart图表数据显示器', 'EChart图表数据显示器,用EChart封装控件实现', moduleName)
@appClient.template('<div style="height:200px;"></div>')
export class echartsDataDisplayer extends baseDataDisplayer {
    /** EChart图表 */
    echartObject?: echartControl.serieObject;
    /** 
     * 显示图表标题
     * @description 默认不显示
     */
    showTitle?: boolean = false;
    /** EChart实例 */
    protected chart: any;
    /** EChart图表数据显示器 */
    constructor() {
        super();
    }
    clearData?(): void {
        this.chart.clear();
    }
    /**
     * 准备数据格式
     */
    prepareDataSchema?(table: any): void {

    }
    /**
     * 添加数据
     */
    setData?(data: platform.dataTable): void {

        let options = this.echartObject.show(data);
        this.chart.setOption(options);
    }
    /**
     * 重置div大小
     */
    onResize?() {
        let parent = $(this.element).parent();
        if (parent.height() > 0) {
            let height = parent.height() - 20 + 'px';
            let width = parent.width() - 20 + 'px';
            $(this.element).css("height", height).css("width", width);
            setTimeout(() => {
                this.chart.resize();
            }, 500);
        }
    }
    onAfterBind?() {
        this.chart = echarts.init(<HTMLDivElement>this.element);
        this.onResize();
        $(this.element).parent().resize(() => {
            this.onResize();
        });
        if (this.showTitle)
            this.echartObject.options.setText(this.caption);

        let options = this.echartObject.getOption();
        if (options) {
            this.chart.setOption(options);
        }
    }
}

/**
 * 图表
 */
@platform.addon("图表", "echart图表", moduleName)
@appClient.template('<div style="height:200px;"></div>')
export class baseEchartDataDisplayer extends baseDataDisplayer {
    /**
     * 图表对象
     */
    protected chart: any;
    /**
     * 关联数据源名称列表
     */
    dataSourceNames?: string[];
    /**
     * 选项
     */
    options: any;
    /**
     * 清除数据
     */


    /**
     * 图表点击事件处理
     */
    echartClick?(param) {

    }


    /**
     * 添加echart点击事件
     */
    addEchartClick?() {
        this.chart.onClick('click', (param) => {
            this.echartClick(param);
        });

    }

    clearData?(): void {
        this.chart.clear();
    }
    /**
     * 准备数据格式
     */
    prepareDataSchema?(columns: platform.dataColumn[]): void {

    }
    /**
     *
     * 对象去重 只能用于本类
     * @param xAxisArray x轴元素
     */
    duplicateRemovalArray(xAxisArray: any): any {
        var temp = []; //一个新的临时数组
        for (var i = 0; i < xAxisArray.length; i++) {
            if (temp.indexOf(xAxisArray[i]) == -1) {
                temp.push(xAxisArray[i]);
            }
        }
        return temp;
    }

    /**
     * 添加数据
     */
    setData?(data: platform.dataTable): void {
    }
    /**
     * 重置div大小
     */
    onResize?() {
        let parent = $(this.element).parent();
        if (parent.height() > 0) {
            let height = parent.height() + 'px';
            let width = parent.width() + 'px';
            $(this.element).css("height", height).css("width", width);
            setTimeout(() => {
                this.chart.resize();
            }, 500);
        }
    }
    onAfterBind?() {
        this.chart = echarts.init(<HTMLDivElement>this.element);
        this.onResize();
        // 为echarts对象加载数据 
        if (this.options) {
            this.chart.setOption(this.options);
        }
        $(this.element).parent().resize(() => {
            this.onResize();
        });
    }

}

/**
 * 折线图表
 */
@platform.addon("折线图表", "echart图表", moduleName)
export class echartBrokenlineDataDisplayer extends baseEchartDataDisplayer {
    /**
     * X轴对应的字段名
     */
    xAxisField: string;
    /**
     * Y轴对应的字段名
     */
    yAxisField: any;
    /**
     * y轴设置
     */
    yAxis: any;
    /**
    * 添加数据
    */
    setData?(data: platform.dataTable): void {
        let that = this;
        let xAxis = [];
        let xTemp = [];
        let series = [];
        that.options.legend = {
            x: 'right',
            textStyle: {
                color: '#000000',
            },
        };
        that.options.legend['data'] = [];
        //创建N个折线
        for (let key of this.yAxisField) {
            let item = {};
            item['name'] = key.name;
            item['type'] = 'line';
            item['data'] = [];
            item['yAxisIndex'] = key.index;
            item['itemStyle'] = { normal: { label: { show: true } } };
            series.push(item);
            //负责创建标题
            let label = {};
            label['name'] = key.name;
            that.options.legend['data'].push(label);
        }
        //存在数据执行下面操作
        if (data) {
            //遍历所有行数据，并进行赋值
            data.rows.forEach((row: any, index: number) => {
                //获取x轴数据
                xTemp.push(row.rowValues[this.xAxisField]);
                //每个点的所有数据（包括行数据）

                //获取折线一个点数据
                for (let key in row.rowValues) {
                    if (key == platform.proto) continue;
                    for (let item of series) {
                        if (item['name'] == key) {
                            let itemdata = {};
                            itemdata['rowdata'] = row.rowValues;
                            if (row.rowValues[key] !== null) {
                                itemdata['value'] = row.rowValues[key];
                                item['data'].push(itemdata);
                            }
                        }
                    }
                }
            });
            xAxis = this.duplicateRemovalArray(xTemp);
            if (that.options.xAxis) {
                that.options.xAxis[0].data = xAxis;
            }
            that.options.series = series;
            that.options.yAxis = this.yAxis;
            that.chart.setOption(this.options);
        }

        //折线图的点击事件
        this.chart.on('click', (param) => {
            this.echartClick(param);
        })
    }
}


/**
*  饼图图表
*/
@platform.addon("饼图图表", "echart图表", moduleName)
export class echartPieDataDisplayer extends baseEchartDataDisplayer {
    /**
     * 数据是否为百分比
     */
    dataIsPercent: boolean;
    /**
     * 饼图需要用到的字段名
     */
    pieFields: any;
    setData?(data: platform.dataTable): void {
        //创建标题
        let legend = {
            orient: 'vertical',
            left: 'left',
            data: []
        };
        for (let key of this.pieFields) {
            legend.data.push(key);
        }

        //获取配置的饼图个数
        let peiCount = this.options.series.length;
        if (data) {
            //遍历所有行数据，每一行数据做一个饼图
            data.rows.forEach((row: any, index: number) => {
                if (index >= this.options.series.length) return;
                this.options.series[index].data = [];
                for (let key of this.pieFields) {
                    let item = {};
                    item['name'] = key;
                    item['value'] = row.rowValues[key];
                    //序号大于饼图个数不可以添加
                    if (index < peiCount)
                        this.options.series[index].data.push(item);
                }
            });
            this.options.legend = legend;
            this.chart.setOption(this.options);
        }
    }
}


@platform.addon("列饼图图表", "echart图表", moduleName)
export class columnechartPieDataDisplayer extends echartPieDataDisplayer {

    setData?(data: platform.dataTable): void {
        //创建标题
        let legend = {
            orient: 'vertical',
            left: 'left',
            data: []
        };
        for (let key of this.pieFields) {
            legend.data.push(key);
        };

        //获取配置的饼图个数
        let peiCount = this.options.series.length;
        if (data) {
            //遍历所有行数据，每一数据做一个饼图
            data.columns.forEach((column: any, index: number) => {
                if (index >= this.options.series.length) return;
                this.options.series[index].data = [];
                for (let key of this.pieFields) {
                    let item = {};
                    item['name'] = key;
                    item['value'] = column.columnValues[key];
                    //序号大于饼图个数不可以添加
                    if (index < peiCount)
                        this.options.series[index].data.push(item);
                }
            });
            this.options.legend = legend;
            this.chart.setOption(this.options);

        }
    }
}
/**
 * EChart带散点地图报表模块
 */
@platform.addon('EChart带散点地图报表模块', 'EChart带散点地图报表模块', moduleName)
export class echartScatterMapDataDisplayer extends baseEchartDataDisplayer {
    /** 经度字段 */
    longitudeField?: string;
    /** 纬度字段 */
    latitudeField?: string;
    /** 名称字段 */
    nameField?: string;
    /** 地图名称 */
    setData?(data: platform.dataTable) {
        var that = this;
        this.options = {
            geo: {
                map: 'foshan',
                scaleLimit: {
                    min: 1,
                    max: 1
                },
                label: {
                    normal: {
                        show: true,
                        textStyle: {
                            fontSize: 10,
                            color: '#ffffff'
                        }
                    },
                    emphasis: {
                        show: true,
                        textStyle: {
                            fontSize: 10,
                            color: '#ffffff'
                        }
                    }
                },
                itemStyle: {
                    normal: {
                        areaColor: '#323c48',
                        borderColor: '#111'
                    },
                    emphasis: {
                        areaColor: '#323c48',
                        borderColor: '#111'
                    }
                }
            },
            // visualMap: {
            //     min: 0,
            //     max: 200,
            //     splitNumber: 5,
            //     inRange: {
            //         color: ['#d94e5d', '#eac736', '#50a3ba'].reverse(),
            //     },
            //     textStyle: {
            //         color: '#fff'
            //     }
            // },
            series: [
                //     {
                //     name: '佛山地图',
                //     type: 'heatmap',
                //     coordinateSystem: 'geo',
                //     data: []
                // }
                {
                    name: '企业热力图',
                    type: 'scatter', // 散点图
                    coordinateSystem: 'geo', // 使用地理坐标系
                    hoverAnimation: 'false',
                    legendHoverLink: 'false',
                    data: [],
                    zlevel: 1
                }
            ]
        };
        //endregion
        if (data) {
            let scatterData = this.convertData(data.rows);
            this.options.series[0].data = scatterData;
        }
        setTimeout(() => {
            this.chart.setOption(this.options);
        }, 1000);
    }
    convertData?(data: platform.dataRow[]) {
        let res = [];
        data.forEach((row: platform.dataRow, index: number) => {
            try {
                if (row.rowValues[this.longitudeField] != null &&
                    row.rowValues[this.latitudeField] != null) {
                    res.push([
                        row.rowValues[this.longitudeField],
                        row.rowValues[this.latitudeField]
                    ]);
                }
            } catch (error) {
                // 如果不存在指定的字段不报错
            }
        })
        return res;
    }
}

/**
*  关系图图表
*/
@platform.addon("关系图图表", "echart图表", moduleName)
export class echartRelationGraphDataDisplayer extends baseEchartDataDisplayer {
    /** 下一级数据获取器集合 
     * @description 格式：数据获取器类型：数据获取器；其中数据获取器类型应该对应categories的配置，且数据获取器类型的值是从数据表获取的
    */
    fetchers?: platform.baseDataFetcher[string];

    /** 数据获取器类型判断数据字段
     * @description 用于判断用哪个数据获取器
     */
    fetcherField: string;

    /** 参数名列表
     * @remark 如:id:code */
    paramKeyList?: any[string];

    /**
     * 需要显示的字段名
     */
    showField: string;

    /**
     * 需要用于查询下一级查询的字段名
     */
    queryField: string;

    /**
     * 额外数据字段
     * @description 保存需要的数据时用于获取数据的字段名
     */
    extendsFields?: string[];

    /**
     * 是否可以拖动点
     */
    draggable?: boolean = true;

    /**
     * 线的指向
     * @description 指定线的指向，源和目标类别，例如："自然人":"企业"
     */
    linePointing?: any[string];

    /**
     * 线指向判断的条件字段
     */
    linePointingFiled?: string;

    setData?(data: platform.dataTable): void {
        let that = this;
        if (data && data.rows && data.rows.length && data.rows.length > 0) {
            that.options.series[0].data = [];
            that.options.series[0].links = [];
            let paramValues: any;
            //遍历所有行数据
            data.rows.forEach((row: any, index: number) => {
                let dataItem = {};
                dataItem['name'] = row.rowValues[that.showField];
                dataItem['category'] = that.fetcherField && that.fetcherField != '' ? (row.rowValues.hasOwnProperty(that.fetcherField) ? row.rowValues[that.fetcherField] : 0) : 0;
                dataItem['draggable'] = this.draggable;
                that.options.series[0].data.push(dataItem);
                paramValues = row.rowValues;
            });
            that.chart.setOption(that.options);
            that.queryNextLevel(paramValues);
        }
    }

    /**
     * 查询下一级节点
     * @param paramValues 参数列表
     */
    queryNextLevel?(paramValues?: {}) {
        let realParamValues = this.getParamValues(paramValues);
        try {
            var fetcherKey = '';
            //获取第一个属性名
            for (var key in this.fetchers) {
                fetcherKey = key;
                break;
            }
            if (this.fetcherField && paramValues[this.fetcherField]) {
                fetcherKey = paramValues[this.fetcherField];
            }
            if (this.fetchers.hasOwnProperty(fetcherKey)) {
                this.fetchers[fetcherKey].query(realParamValues, 0, Number.MAX_SAFE_INTEGER)
                    .then(table => {
                        if (table) {
                            let options = this.chart.getOption();
                            let nextParamValues: any = [];
                            //遍历所有行数据
                            table.rows.forEach((row: any, index: number) => {
                                //准备添加的点不存在的标识
                                let isItemExist: boolean = false;
                                //名称相同的点对象
                                var sameNameItem = this.checkItemExistByName(options.series[0].data, row.rowValues[this.showField]);
                                //记录名称类似的点的数量
                                let num: number = 0;
                                //判断准备添加的点是否存在
                                if (sameNameItem != null) {
                                    //如果根据名称获取到准备添加的点存在则判断额外的数据是否相同
                                    if (this.checkItemExtendsData(sameNameItem, row.rowValues)) {
                                        //如果额外的数据都相同，则说明点真的存在
                                        isItemExist = true;
                                    } else {
                                        //如果额外的数据不相同，则说明点只是名称相同，具体对象是不同的，还是需要添加新的点对象
                                        let regex = "/^{0}$|^{0}_[0-9]+$/g";
                                        //获取名称类似的点的数量
                                        num = this.getMatchNameItemNum(options.series[0].data, platform.format(regex, row.rowValues[this.showField]));
                                    }
                                }
                                //判断点对象是否存在
                                if (!isItemExist) {
                                    //添加点数据
                                    let dataItem = {};
                                    //因为名称不能相同，则名称相同的点自动添加“_数字”的标识
                                    dataItem['name'] = num > 0 ? row.rowValues[this.showField] + "_" + num.toString() : row.rowValues[this.showField];
                                    //通过获取的数据指定类别，如果没有数据则默认类型为1
                                    dataItem['category'] = this.fetcherField && this.fetcherField != '' ? (row.rowValues.hasOwnProperty(this.fetcherField) ? row.rowValues[this.fetcherField] : 1) : 1;
                                    dataItem['draggable'] = this.draggable;
                                    //存入额外的数据
                                    if (this.extendsFields && this.extendsFields.length && this.extendsFields.length > 0) {
                                        let extendsData = {};
                                        for (let key in this.extendsFields) {
                                            if (key == platform.proto) break;
                                            let element = this.extendsFields[key];
                                            if (row.rowValues.hasOwnProperty(element)) {
                                                extendsData[element] = row.rowValues[element];
                                            }
                                        }
                                        dataItem['extendsData'] = extendsData;
                                    }
                                    options.series[0].data.push(dataItem);

                                    //添加下一级查询参数
                                    if (this.queryField && this.queryField != '') {
                                        if (row.rowValues[this.queryField] != paramValues[this.queryField]) {
                                            nextParamValues.push(row.rowValues);
                                        }
                                    } else {
                                        nextParamValues.push(row.rowValues);
                                    }
                                }
                                //添加关系数据
                                let linkItem = {};
                                if (this.linePointing && this.linePointingFiled) {
                                    for (var source in this.linePointing) {
                                        if (source == platform.proto) break;
                                        if (this.linePointing.hasOwnProperty(source)) {
                                            var target = this.linePointing[source];
                                            if (row.rowValues[this.linePointingFiled] == target) {
                                                linkItem['source'] = paramValues[this.showField];
                                                linkItem['target'] = num > 0 ? row.rowValues[this.showField] + "_" + num.toString() : row.rowValues[this.showField];
                                            } else if (row.rowValues[this.linePointingFiled] == source) {
                                                linkItem['source'] = num > 0 ? row.rowValues[this.showField] + "_" + num.toString() : row.rowValues[this.showField];
                                                linkItem['target'] = paramValues[this.showField];
                                            } else {
                                                linkItem = null;
                                            }
                                        }
                                    }
                                } else {
                                    linkItem['source'] = num > 0 ? row.rowValues[this.showField] + "_" + num.toString() : row.rowValues[this.showField];
                                    linkItem['target'] = paramValues[this.showField];
                                }
                                if (linkItem != null && !this.checkLinkItemExist(options.series[0].links, linkItem)) {
                                    options.series[0].links.push(linkItem);
                                }

                            });

                            this.chart.setOption(options);
                            this.options = options;

                            if (nextParamValues && nextParamValues.length > 0) {
                                for (var item of nextParamValues) {
                                    let that = this;
                                    this.queryNextLevel(item);
                                }

                            }
                        }
                    });
            }
        } catch (error) {

        }
    }

    /**
     * 获取参数
     * @param paramValues 查询参数
     */
    getParamValues?(paramValues?: any[string]) {
        if (this.paramKeyList) {
            let params = {};
            for (let key in this.paramKeyList) {
                let name = this.paramKeyList[key];
                if (paramValues[name]) {
                    params[key] = paramValues[name];
                }
            }
            return params;
        }
        return paramValues;
    }


    /**
     * 获取匹配名称的字符串
     * @param array 需要检查的数组
     * @param matchName 用于匹配名称的正则表达式字符串
     * @returns 返回匹配的名称数量
     */
    getMatchNameItemNum?(array: any, matchName: string): number {
        let count: number = 0;
        for (var key in array) {
            if (key == platform.proto) break;
            if (array.hasOwnProperty(key)) {
                var item = array[key];
                if (item.hasOwnProperty("name") && item.name && typeof item.name == "string" && (<string>item.name).match(eval(matchName)) != null) {
                    count++;
                }
            }
        }
        return count;
    }

    /**
     * 根据名称检查item是否存在
     * @param array 需要检查的数组
     * @param rowValues 用于检查的行数据
     * @returns 存在则返回改item对象，否则返回null
     */
    checkItemExistByName?(array: any, name: string) {
        for (var key in array) {
            if (key == platform.proto) break;
            if (array.hasOwnProperty(key)) {
                var item = array[key];
                if (item.hasOwnProperty("name") && item.name && item.name == name) {
                    return item;
                }
            }
        }
        return null;
    }

    /**
     * 检测对象的额外数据是否和行数据相同
     * @param item 需要检测的对象
     * @param rowValues 行数据
     * @returns 不存在额外的数据或额外的数据相同则返回true，否则返回false
     */
    checkItemExtendsData?(item: any, rowValues: any): boolean {
        //存在额外的数据则检查额外的数据是否相同
        if (item.extendsData) {
            for (let key in item.extendsData) {
                //如果key为platform.proto（兼容IE8） 或 如果key对应的值为undefined，则跳过
                if (key == platform.proto || item.extendsData[key] == undefined || rowValues[key] == undefined) {
                    break;
                }
                //如果储存的额外数据和需要检查的数据不相同则返回item不存在
                if (item.extendsData[key] != rowValues[key]) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 检测关系数据对象是否已经存在
     * @param array 需要检测的数组
     * @param linkItem 需要检测的对象
     * @param 存在返回true，否则返回false
     */
    checkLinkItemExist?(array: any, linkItem: {}) {
        for (var key in array) {
            if (key == platform.proto) break;
            if (array.hasOwnProperty(key)) {
                var item = array[key];
                if (linkItem.hasOwnProperty('source') && linkItem.hasOwnProperty('target') && item.hasOwnProperty('source') && item.hasOwnProperty('target')
                    && ((linkItem['source'] == item['source'] && linkItem['target'] == item['target'])
                        || (linkItem['source'] == item['target'] && linkItem['target'] == item['source']))) {
                    return true;
                }
            }
        }
        return false;
    }
}

/**
 * 表格
 */
// @platform.addon("表格", "`表格数据显示器`", moduleName)
// @appClient.template(`<table class= "table table-condensed table-hover">
// <thead name="theader"> </thead><tbody name="tbody"></tbody >
// </table><div class="text-center"></div>`)
// export class gridDataDisplayer extends baseDataDisplayer implements dataQueryer {
//     /** 表格标题 */
//     $theader?: JQuery = undefined;
//     /** 表格数据 */
//     $tbody?: JQuery = undefined;
//     $previous?: JQuery = undefined;
//     $next?: JQuery = undefined;
//     /**
//      * 关联数据源名称列表
//      */
//     dataSourceNames?: string[];
//     /** 过滤的字段列表 */
//     filtFields?: string[];
//     private thead?: boolean = false;

//     /**
//      * 清除数据
//      */
//     clearData?(): void {

//     }
//     /**
//      * 准备数据格式
//      */
//     prepareDataSchema?(table: platform.dataTable): void {
//         if (table && table.columns) {
//             let columns = table.columns;
//             let tr = $(`<tr></tr>`);
//             for (let key in columns) {
//                 if (key == platform.proto) continue;
//                 if (key == "RN") continue;
//                 if (this.filtFields
//                     && this.filtFields.indexOf(key) > -1) continue;
//                 let uiColumn = findColumnByFieldName(this.columns, key);
//                 if (uiColumn && uiColumn.hideable) continue;
//                 let column = columns[key];
//                 //let title = column.caption ? column.caption : column.name;
//                 let title = (uiColumn && uiColumn.header) ? uiColumn.header : column.name;
//                 let th = $(`<th>${title}</th>`);
//                 th.appendTo(tr);
//             }
//             tr.appendTo(this.$theader);
//             this.thead = true;
//         }
//     }
//     /**
//      * 查询
//      */
//     query?() {

//     }
//     /**
//      * 事件:执行查询
//      */
//     doQuery?: (dataSourceName: string, paramValues: any[string], startIndex: number, maxCount: number) => void;
//     /**
//      * 自动查询时间间隔（单位：毫秒），如果大于零，表示自动执行；如果小于等于0，表示手动执行
//      */
//     autoQueryInterval?: number;

//     /**
//      * 设置数据
//      * @param data 数据
//      */
//     setData?(data: platform.dataTable): void {
//         if (data) {
//             if (!this.thead) {
//                 this.prepareDataSchema(data.columns);
//             }
//             if (data.rows.length > 0) {
//                 this.$tbody.html("");
//                 for (let row of data.rows) {
//                     let tr = $(`<tr></tr>`);
//                     for (let key in row.rowValues) {
//                         if (key == platform.proto) continue;
//                         if (key == "RN") continue;
//                         if (this.filtFields
//                             && this.filtFields.indexOf(key) > -1) continue;
//                         let uiColumn = findColumnByFieldName(this.columns, key);
//                         if (uiColumn && uiColumn.hideable) continue;
//                         let value = row.rowValues[key] != null ? row.rowValues[key] : "";
//                         value = formatValueByColumn(value, uiColumn);
//                         let td = $(`<td>${value}</td>`);
//                         td.appendTo(tr);
//                     }
//                     tr.click(() => {
//                         tr.parent().find("tr.focus").toggleClass("focus");//取消原先选中行
//                         tr.toggleClass("focus");//设定当前行为选中行
//                         for (let dataSourceName of this.dataSourceNames) {
//                             if (this.doQuery)
//                                 this.doQuery(dataSourceName, row.rowValues, 0, Number.MAX_SAFE_INTEGER);
//                         }
//                     })
//                     tr.appendTo(this.$tbody);
//                 }
//             } else {
//                 this.$tbody.html("");
//             }
//         }
//     }
// }


/**
 * 数据服务获取器
 * @remark 通过数据服务获取数据的数据获取器
 */
@platform.addon("数据服务获取器", "通过数据服务获取数据的数据获取器", moduleName)
export class dataServiceFetcher extends platform.baseDataFetcher {
    /**
     * 数据服务
     */
    dataService?: platform.IDataService | platform.factory;
    /**
     * 命令ID
     */
    command?: string;
    /**
     * 查询
     * @param command 查询命令，可以是命令ID也可以是命令字符串
     * @param startIndex 起始索引
     * @param maxCount 最大行数
     * @param paramValues 参数值
     */
    query?(paramValues: {}, startIndex: number = 0, maxCount: number = 500): Promise<platform.dataTable> {
        if (!this.dataService) {
            return Promise.reject(new Error(`数据服务不存在`));
        }
        if (!this.command) {
            return Promise.reject(new Error(`当前获取器不存可执行的命令ID`));
        }
        if (!this.name) {
            return Promise.reject(new Error(`当前获取器的数据表明不存在`));
        }
        // 获取数据服务
        let service = platform.getObject(this.dataService);
        return service.query(this.command, paramValues, startIndex, maxCount);
    }
    /** 获取表结构 */
    getTableSchema?(): Promise<platform.dataTable> {
        let service = platform.getObject(this.dataService);
        return service.getTableSchema(this.command);
    }
}


/**
 * 明细表格显示器
 */
@platform.addon("明细表格", "明细表格数据显示器", moduleName)
@appClient.template(`<div class="container-fluid" style="margin-top:25px;">
<div class="row-fluid">
    <div class="col-md-6">
    <div class="dl-horizontal" name="cloumnone">
        </div>
    </div>
    <div class="col-md-6">
        <div class="dl-horizontal" name="cloumntwo">
        </div>
    </div>
</div>
</div>`)
export class detailedDataDisplayer extends baseDataDisplayer {

    /**
     * 行1
     */
    $cloumnone?: JQuery = undefined;


    /**
     * 行2
     */
    $cloumntwo?: JQuery = undefined;

    /**
         * 关联数据源名称列表
         */
    dataSourceNames?: string[];
    /**
     * 清除数据
     */
    clearData?(): void {

    }

    /**
     * 清空表格
     */
    clearform?(): void {

    }
    /**
     * 准备数据格式
     */
    prepareDataSchema?(table: platform.dataTable): void {

    }
    /**
     * 设置数据
     * @param data 数据
     */
    setData?(data: platform.dataTable): void {
        $(this.$cloumnone).find("dd").html("");
        $(this.$cloumnone).find("dt").html("");
        $(this.$cloumntwo).find("dd").html("");
        $(this.$cloumntwo).find("dt").html("");
        if (data.rows.length > 0) {
            let dtContainer1 = $(this.$cloumnone).find("dt");
            let dtContainer2 = $(this.$cloumntwo).find("dt");
            data.rows.forEach((row, index) => {
                //只获取第一行数据处理
                if (index == 0) {
                    let num = 1;
                    for (let key in row.rowValues) {
                        if (key == platform.proto) continue;
                        if (key == "RN") continue;
                        let dt = $(`<dt> ${key} :</dt>`);
                        let dd = $(`<dd>${row.rowValues[key] != null ? row.rowValues[key] : ""}</dd>`);
                        if (num % 2 == 0) {
                            dt.appendTo(this.$cloumntwo);
                            dd.appendTo(this.$cloumntwo);
                        } else {
                            dt.appendTo(this.$cloumnone);
                            dd.appendTo(this.$cloumnone);
                        }
                        num += 1;
                    }
                }
            });
        }
    }

}

@platform.addon("BootstrapTable显示器", "BootstrapTable显示器", moduleName)
@appClient.template(`<table name="table">
<thead name="theader"></thead><tbody name="tbody"></tbody>
</table><div class="text-center"></div><div class="pull-left" name="leftTile">
<span >第</span>
<input type="text"  name="curPageControl" class="text-center" style="width:35px;"/>
<span >页</span>
<a href="#">/</a>
<span>总</span>
<a href="#" name="totalPageControl">0</a>
<span >页</span>
<button class="btn btn-default"  name="btnGO">转到</button>
</div>	
<div class=" pull-right" >
<button class="btn btn-default"  name="btnPre">上一页</button>
<button class="btn btn-default" name="btnNext">下一页</button>
<button class="btn btn-default" name="btnMore" style="display:none;">更多</button>
</div>`)
export class gridDataDisplayer extends baseDataDisplayer implements dataQueryer {
    /** 表格 */
    $table?: JQuery = undefined;
    /** 表格标题(表头) */
    $theader?: JQuery = undefined;
    /** 表格数据 */
    $tbody?: JQuery = undefined;
    /**
     * 上一页
     */
    $btnPre?: JQuery = undefined;
    /**
     * 下一页
     */
    $btnNext?: JQuery = undefined;
    /**
     * 更多按钮
     */
    $btnMore?: JQuery = undefined;
    /**
     * 转到按钮
     */
    $btnGO?: JQuery = undefined;
    /**
     * 总页数
     */
    $totalPageControl?: JQuery = undefined;
    /**
     * 当前页数控件
     */
    $curPageControl?: JQuery = undefined;
    /**
     * 页数控件
     */
    $leftTile?: JQuery = undefined;
    /**
     * 关联数据源名称列表
     */
    dataSourceNames?: string[];
    /** 过滤的字段列表 */
    filtFields?: string[];
    /**
     * 是否需要分页(默认为分页)
     */
    isPaging?: boolean = true;
    /**
     * 每页显示条数（默认显示10条数据）
     */
    pageSize?: number = 10;
    /**
     * 当前页面数
     */
    currentPageNum?: number = 1;
    /**
     * 总页面数
     */
    totalPageNum?: number = 0;
    /**
     * 所有的行数据
     */
    totalRows?: any[];
    /**
     * 总行数
     */
    totalRowNum?: number;
    /**
     * 分页查询条数
     */
    queryCount?: number = 100;
    /**
    * 清除数据
    */
    clearData?(): void {
        this.totalRows = [];
        this.totalPageNum = 0;
        this.currentPageNum = 0;
        this.totalRowNum = 0;
    }
    /**
    * 查询
    */
    query?() {

    }
    /**
     * 事件:执行查询
     */
    doQuery?: (dataSourceName: string, paramValues: any[string], startIndex: number, maxCount: number) => void;
    /** 
     * 事件分页查询
     */
    doPageQuery?: (dataSourceName: string, startIndex: number, maxCount: number) => Promise<any>;
    /**
     * 自动查询时间间隔（单位：毫秒），如果大于零，表示自动执行；如果小于等于0，表示手动执行
     */
    autoQueryInterval?: number;
    /**
    * 准备数据格式
    */
    prepareDataSchema?(table: platform.dataTable): void {
        //获取表头数据
        let columnsTitle = []; // 列标题
        if (table.columns) {
            let columns = table.columns;
            for (let key in columns) {
                if (key == platform.proto) continue;
                if (key == "RN") continue;
                if (this.filtFields
                    && this.filtFields.indexOf(key) > -1) continue;
                let uiColumn = findColumnByFieldName(this.columns, key);
                if (uiColumn && uiColumn.hideable) continue;
                let column = columns[key];
                let title = (uiColumn && uiColumn.header) ? uiColumn.header : column.name;
                columnsTitle.push({
                    field: column.name,
                    title: title
                });
            }
        }
        //初始化bootstrapTable
        this.$table.bootstrapTable({
            height: this.getHeight(),
            clickToSelect: true,
            sidePagination: "client",
            pagination: this.isPaging,
            pageNumber: 1,
            pageSize: this.pageSize,
            pageList: [this.pageSize],
            columns: columnsTitle
        });
    }
    /**
     * 设置数据
     * @param data 
     */
    setData?(data: platform.dataTable): void {
        this.currentPageNum = 1;
        if (this.isPaging) {
            //计算总页数
            let pageTotalTemp = Math.ceil(data.rows.length / this.pageSize);
            this.$totalPageControl[0].innerText = pageTotalTemp.toString();
            this.totalPageNum = pageTotalTemp;
            //设置当前页数
            this.$curPageControl.val(this.currentPageNum.toString());
            this.totalRowNum = data.rows.length;
        }
        //初始化数据
        this.totalRows = this.dataTableToRowData(data);
        this.$table.bootstrapTable('load', this.totalRows);
        if (this.currentPageNum == this.totalPageNum)
            this.$btnMore.show();
    }


    /**
    * 计算父窗体高度
    */
    getHeight() {
        return $(this.element).parent().height() - this.$leftTile.height() - 10;
    }

    /**
     * dataTable的数据转换为 bootstraptable 
     * @param data 数据
     */
    dataTableToRowData(data: platform.dataTable): any {
        let rowsData = []; // 行数据
        if (data.rows.length > 0) {
            for (let row of data.rows) {
                let fieldValues = {};
                for (let key in row.rowValues) {
                    if (key == platform.proto) continue;
                    if (key == "RN") continue;
                    if (this.filtFields
                        && this.filtFields.indexOf(key) > -1) continue;
                    fieldValues[key] = row.rowValues[key] != null ? row.rowValues[key] : "";
                }
                rowsData.push(fieldValues);
            }
        }
        return rowsData;
    }

    onAfterBind?() {
        //绑定事件上下页事件
        if (this.isPaging) {
            this.$btnPre.click(() => {
                if (this.currentPageNum > 1) {
                    this.currentPageNum--;
                    //设置当前页数
                    this.$curPageControl.val(this.currentPageNum.toString());
                    this.$table.bootstrapTable('prevPage');
                }
                if (this.currentPageNum < this.totalPageNum)
                    this.$btnMore.hide();
            });
            this.$btnNext.click(() => {
                if (this.currentPageNum == this.totalPageNum) {

                } else {
                    this.currentPageNum++;
                    //设置当前页数
                    this.$curPageControl.val(this.currentPageNum.toString());
                    //如果当前页数与总页数相等
                    if (this.currentPageNum == this.totalPageNum) {
                        this.$btnMore.show();
                    }
                    this.$table.bootstrapTable('nextPage');
                }
            });
            //绑定事件转到按钮
            this.$btnGO.click(() => {
                this.$table.bootstrapTable('selectPage', this.$curPageControl.val());
                this.currentPageNum = parseInt(this.$curPageControl.val());
                //最后一页时候显示更多按钮
                if (this.currentPageNum == this.totalPageNum) {
                    this.$btnMore.show();
                } else {
                    this.$btnMore.hide();
                }

            });
            //绑定更多按钮
            this.$btnMore.click(() => {
                for (let key in this.dataViews) {
                    this.doPageQuery(this.dataViews[key].dataSourceName, this.totalRowNum, this.queryCount).then(table => {
                        if (table.rows.length == 0)
                            alert("已经没有数据");
                        else {
                            //合并数据，dataTable重新加载数据
                            this.totalRows = this.totalRows.concat(this.dataTableToRowData(table));
                            this.$table.bootstrapTable('load', this.totalRows);
                            this.$table.bootstrapTable('selectPage', this.currentPageNum);
                            //重新设置显示的总页数（因为数据行数已经发生改变）
                            this.totalRowNum = this.totalRows.length;
                            this.totalPageNum = Math.ceil(this.totalRows.length / this.pageSize);
                            this.$totalPageControl.text(this.totalPageNum.toString());
                        }
                        this.$btnMore.hide();
                    });
                }
            });
        }
    }
}
/**
 * 表格列的扩展
 * @author chencx（陈楚溪）
 */
@platform.addon("表格列", "定义表格内部与列相关的配置，其中包括列标题及数据展示", moduleName)
export class gridColumn extends platform.baseObject {
    /** 设置列与数据集中数据的对应关系，值为数据模型中的字段名称 */
    dataIndex?: string;
    /** 列标题 */
    header?: string;
    /** 隐藏该列，默认为false */
    hideable?: boolean = false;
}

@platform.addon("布尔列", "布尔列", moduleName)
export class booleanColumn extends gridColumn {
    /** 渲染false值对应的文本，默认为false */
    falseText?: string = "false";
    /** 渲染true值对应的文本，默认为true */
    trueText?: string = "true"
    /** 渲染空值对应的文本，默认为空字符串 */
    undefinedText?: string = "";
}

@platform.addon("数字列", "数字列", moduleName)
export class numberColumn extends gridColumn {
    /** 设置numeral函数的格式化字符串，列如：0,000.00 */
    format?: string;
}

@platform.addon("日期列", "日期列", moduleName)
export class dateColumn extends gridColumn {
    /** 列类型 */
    readonly ctype?: string = "datecolumn";
    /** 设置DateUtil.format函数的格式化字符串，默认为yyyy-MM-dd hh:mm:ss */
    format?: string = "yyyy-MM-dd hh:mm:ss";
}

@platform.addon("模板列", "存在{0}的模板列", moduleName)
export class templateColumn extends gridColumn {
    /** 模板字符串，例子："{0}，你好！"，模板数据将会被传入并替换{0} */
    tpl?: string = "{0}";
}

/**
 * 通过字段名称查找表格列
 * @param columns 列数组
 * @param fieldName 字段名称
 */
export function findColumnByFieldName(columns: gridColumn[], fieldName: string): gridColumn {
    let ret;
    if (!columns)
        return ret;
    for (let column of columns) {
        // 忽略列名大小写
        if (column.dataIndex.toLocaleUpperCase() == fieldName.toLocaleUpperCase()) {
            ret = column;
            break;
        }
    }
    return ret;
}

/**
 * 通过列的配置项格式化数据值
 * @param value 
 * @param column 
 */
export function formatValueByColumn(value: any, column: gridColumn): any {
    if (!value || !column)
        return value;
    platform.fetchAddonProtoType(column);
    if (column instanceof booleanColumn) {
        if (value == true || value == "true") {
            value = (<booleanColumn>column).trueText;
        } else if (value == false || value == "false") {
            value = (<booleanColumn>column).falseText;
        } else {
            value = (<booleanColumn>column).undefinedText;
        }
    } else if (column instanceof dateColumn) {
        value = platform.dateUtil.format((<dateColumn>column).format, new Date(value));
    } else if (column instanceof numberColumn) {
        if ((<numberColumn>column).format)
            value = numeral(value).format((<numberColumn>column).format);
    } else if (column instanceof templateColumn) {
        value = platform.format((<templateColumn>column).tpl, value);
    }
    return value;
}
/** 表格列的扩展 */


